﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using WTwitter.Model.Framework;
using WTwitter.Model.Framework.TextSplitter;
using WTwitter.Model.UserData;
using WTwitter.Model.Filters;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using WTwitter.ViewModel.Utility;

namespace WTwitter.ViewModel {
	/// <summary>
	/// タイムラインで表示する1アイテムを表すViewModel
	/// </summary>
	sealed public class TimelineItemViewModel : ViewModelBase, IEquatable<TimelineItemViewModel> {

		#region static member
		private static BitmapImage _replyImage = App.Current.FindResource("CommentsImage") as BitmapImage;
		private static BitmapImage _reTweetImage = App.Current.FindResource("ReTweetImage") as BitmapImage;
		private static BitmapImage _replyToMailImage = App.Current.FindResource("ReturnMessageImage") as BitmapImage;
		private static BitmapImage _favoritedImage = App.Current.FindResource("FavoriteImage") as BitmapImage;
		private static BitmapImage _favoritedEmptyImage = App.Current.FindResource("FavoriteEmptyImage") as BitmapImage;
		#endregion

		#region private member
		private ITimelineItem _item;
		private AuthInfo _authInfo;
		private string _createdAtString;
		private string _relativeTimeString;
		private ToggleImageButton _favoriteImageButton;
		private UserViewModel _userVM;
		#endregion

		public TimelineItemViewModel(ITimelineItem item, AuthInfo info)
			: base (""){
			_item = item;
			_authInfo = info;
			_userVM = new UserViewModel(item.User, _authInfo.User);

			//アプリケーションの.exeがあるフォルダ
			var baseUri = System.IO.Directory.GetParent(
				System.Reflection.Assembly.GetExecutingAssembly().Location).FullName;

			//アイテムのタイプに応じて表示するボタンを変更
			switch (item.Type) {
				case ItemType.TwitterStatus:
				case ItemType.SearchTwitter:
					_favoriteImageButton = new ToggleImageButton("Favorite", ToggleFavoriteCommand, _favoritedImage, _favoritedEmptyImage);
					_favoriteImageButton.IsOn = Favorited;
					Commands = new ImageButton[] {
						new ImageButton("返信", ReplyCommand, _replyImage),
						new ImageButton("ReTweet", RTCommand, _reTweetImage),
						_favoriteImageButton
					};
					break;
				case ItemType.DirectMessage:
					Commands = new ImageButton[] {
						new ImageButton("DirectMessage返信", ReplyToMailCommand, _replyToMailImage)
					};
					break;
				case ItemType.Other:
					Commands = new ImageButton[] { };
					break;
				default:
					throw new InvalidOperationException();
			}
			Update();
		}

		#region Command

		#region Reply
		private RelayCommand _replyCommand;
		public RelayCommand ReplyCommand {
			get {
				if (_replyCommand == null) {
					_replyCommand = new RelayCommand(this.OnReplyCommandRequested);
				}
				return _replyCommand;
			}
		}

		private void OnReplyCommandRequested(object parameter) {
			var references = TimelineItemVMCache.Instance.GetSequenceOfConversation(this).ToList<TimelineItemViewModel>();
			var vm = new SubmitPanelViewModel(_authInfo, this.Item,
				new TimelineViewModel("", references, ListSortDirection.Ascending));
			vm.SetTextToReply();
			Utility.ViewConnector.Instance.Show(vm);
		}
		#endregion

		#region RT
		private RelayCommand _RTCommand;
		public RelayCommand RTCommand {
			get {
				if (_RTCommand == null) {
					_RTCommand = new RelayCommand(this.OnRTCommandRequested);
				}
				return _RTCommand;
			}
		}

		private void OnRTCommandRequested(object parameter) {
			var references = TimelineItemVMCache.Instance.GetSequenceOfConversation(this).ToList<TimelineItemViewModel>();
			var vm = new SubmitPanelViewModel(_authInfo, this.Item,
				new TimelineViewModel("", references, ListSortDirection.Ascending));
			vm.SetTextToReTweet();
			Utility.ViewConnector.Instance.Show(vm);
		}

		#endregion

		#region ReplyToMail
		private RelayCommand _replyToMailCommand;
		public RelayCommand ReplyToMailCommand {
			get {
				if (_replyToMailCommand == null) {
					_replyToMailCommand = new RelayCommand(this.OnReplyToMailRequested);
				}
				return _replyToMailCommand;
			}
		}

		private void OnReplyToMailRequested(object parameter) {
			var vm = new SubmitPanelViewModel(_authInfo, this.Item,	new TimelineViewModel("", new TimelineItemViewModel[] {this}));
			vm.SetTextToMail();
			Utility.ViewConnector.Instance.Show(vm);
		}
		#endregion

		#region SetNGUser
		private RelayCommand _setNgUserCommand;
		public RelayCommand SetNgUserCommand {
			get {
				if (_setNgUserCommand == null) {
					_setNgUserCommand = new RelayCommand(this.OnSetNgUserRequested);
				}
				return _setNgUserCommand;
			}
		}

		private void OnSetNgUserRequested(object parameter) {
			//TODO NgFilterByIdクラス内で自分でOptionを更新するようにした方がいいかも？
			Option.Instance.AddNg(FilterTargetType.Id, Item.User.ScreenName);
			NgFilterById.Common.AddNg(Item.User.ScreenName);
		}
		#endregion

		#region ShowUsersAllItem

		private RelayCommand _showUsersAllItemCommand;

		/// <summary>
		/// このアイテムのユーザーのすべての発言を表示する
		/// </summary>
		public RelayCommand ShowUsersAllItemCommand {
			get {
				if (_showUsersAllItemCommand == null) {
					_showUsersAllItemCommand = new RelayCommand(this.OnShowUsersAllItem);
				}
				return _showUsersAllItemCommand;
			}
		}

		private void OnShowUsersAllItem(object parameter) {
			var vm = new TimelineViewModel("",	TimelineItemVMCache.Instance.GetAllItemsOf(this.Name));
			Utility.ViewConnector.Instance.Show(vm);
		}
		#endregion

		#region ToggleFavoriteCommand

		private RelayCommand _toggleFavoriteCommand;
		public RelayCommand ToggleFavoriteCommand {
			get {
				if (_toggleFavoriteCommand == null) {
					_toggleFavoriteCommand = new RelayCommand(this.OnToggleFavorite);
				}
				return _toggleFavoriteCommand;
			}
		}

		private void OnToggleFavorite(object parameter) {
			if (_item.Type != ItemType.TwitterStatus) {
				return;
			}
			var before = Favorited;
			var target = _item as Model.Twitter.TwitterItem;
			var result = target.RequestToChangeFavoritedValue(!Favorited, _authInfo);
			if (result != before) {
				OnPropertyChanged("Favorited");
				_favoriteImageButton.IsOn = result;
			}
		}
		#endregion

		#endregion

		#region Property
		public string TypeOfSourceTimeline {
			get { return _item.TypeOfSourceTimeline; }
		}

		public ITimelineItem Item {
			get { return _item; }
		}

		public long Id {
			get { return _item.Id; }
		}

		public UserViewModel User {
			get { return _userVM; }
		}

		public long? InReplyTo {
			get { return _item.InReplyTo; }
		}

		public string Text {
			get { return _item.Text; }
		}

		public string Name {
			get { return _item.User.ScreenName; }
		}

		public string ProfileImageUrl {
			get { return _item.User.ProfileImageUrl; }
		}

		public DateTime CreatedAt {
			get { return _item.CreatedAt; }
		}

		public string CreatedAtString {
			get {
				if (string.IsNullOrEmpty(_createdAtString)) {
					_createdAtString = CreatedAt.ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss");
				}
				return _createdAtString;
			}
		}

		public string RelativeTimeString {
			get { return _relativeTimeString; }
			private set {
				if (_relativeTimeString != value) {
					_relativeTimeString = value;
					OnPropertyChanged("RelativeTimeString");
				}
			}
		}

		public bool Favorited {
			get { return _item.Favorited; }
		}

		public List<TextComponent> TextComponents {
			get {
				Debug.Assert(Item.TextComponents != null);
				return _item.TextComponents; 
			}
		}

		public string DetailDescription {
			get { return _item.DetailDescription; }
		}

		/// <summary>
		/// 投稿したユーザのタイムラインを表示するURL
		/// </summary>
		public string UserUrl {
			get { return _item.User.UserUrl; }
		}

		public ImageButton[] Commands { get; set; }

		#endregion

		public override string ToString() {
			return "TimelineItemViewModel:" + Id.ToString();
		}

		public void Update() {
			//？？分前の表記の更新
			var span = DateTime.Now - CreatedAt;
			if (span.Days > 0) {
				RelativeTimeString = string.Format("{0}日前", span.Days);
			} else if (span.Hours > 0) {
				RelativeTimeString = string.Format("{0}時間前", span.Hours);
			} else if (span.Minutes > 0) {
				RelativeTimeString = string.Format("{0}分前", span.Minutes);
			} else {
				RelativeTimeString = span.Seconds > 0 ? string.Format("{0}秒前", span.Seconds) : "0秒前";
			}
		}

		#region IEquatable<TimelineItemViewModel> メンバ

		public bool Equals(TimelineItemViewModel other) {
			//メモ：
			//TimelineItemが同じでTimelineItemViewModelが異なるというケースは今のところ考えていないので
			//とりあえずItemで比較している
			return this.Item.Equals(other.Item);
		}

		#endregion
	}
}
